﻿using IOP.SgrA.GLSL;
using IOP.SgrA.SilkNet.Vulkan;
using IOP.SgrA.SilkNet.Vulkan.Scripted;

namespace VkSample127
{
    [ShaderVersion("460")]
    [GLSLExtension("GL_ARB_separate_shader_objects : enable")]
    [GLSLExtension("GL_ARB_shading_language_420pack : enable")]
    public partial class CartoonishFrag : GLSLFrag
    {
        [SampledImage(0, 0, DescriptorSetTarget.RenderObject)]
        public sampler2D uImageUnit { get; set; }

        [ShaderInput(0)]
        public vec2 vST {  get; set; }
        [FragOutput(0, false)]
        public vec4 outColor { get; set; }
        public override void main()
        {
            float uMagTol = 0.2f;//设定的阈值，判定当前点是否为边缘点
            float uQuantize = 18.0f;//阈值量化因子
            ivec2 ires = textureSize(uImageUnit, 0);        //获得纹理图的宽高度
            float uResS = ires.x;                    //获得纹理图的S值
            float uResT = ires.y;                    //获得纹理图的T值
            vec3 rgb = texture(uImageUnit, vST).rgb;        //获得纹理采样的rgb值
            vec2 stp0 = new vec2(1.0f / uResS, 0.0f);         //与左右相邻像素间的距离向量
            vec2 st0p = new vec2(0.0f, 1.0f / uResT);         //与上下相邻像素间的距离向量
            vec2 stpp = new vec2(1.0f / uResS, 1.0f / uResT);     //与左下、右上相邻像素间的距离向量
            vec2 stpm = new vec2(1.0f / uResS, -1.0f / uResT);        //与左上、右下相邻像素间的距离向量
            vec3 W = new vec3(0.2125f, 0.7154f, 0.0721f);
            float im1m1 = dot(texture(uImageUnit, vST - stpp).rgb, W);
            float ip1p1 = dot(texture(uImageUnit, vST + stpp).rgb, W);
            float im1p1 = dot(texture(uImageUnit, vST - stpm).rgb, W);
            float ip1m1 = dot(texture(uImageUnit, vST + stpm).rgb, W);
            float im10 = dot(texture(uImageUnit, vST - stp0).rgb, W);//左边相邻点的灰度值
            float ip10 = dot(texture(uImageUnit, vST + stp0).rgb, W);//右边相邻点的灰度值
            float i0m1 = dot(texture(uImageUnit, vST - st0p).rgb, W);//上边相邻点的灰度值
            float i0p1 = dot(texture(uImageUnit, vST + st0p).rgb, W);//下边相邻的点的灰度值
                                                                     //与图像作平面卷积计算，分别得出横向及纵向的亮度差分近似值，即sobel算子的横纵灰度值
            float h = -1.0f * im1p1 - 2.0f * i0p1 - 1.0f * ip1p1 + 1.0f * im1m1 + 2.0f * i0m1 + 1.0f * ip1m1;
            float v = -1.0f * im1m1 - 2.0f * im10 - 1.0f * im1p1 + 1.0f * ip1m1 + 2.0f * ip10 + 1.0f * ip1p1;
            float mag = length(new vec2(h, v));
            if (mag > uMagTol) outColor = new vec4(0.0f, 0.0f, 0.0f, 1.0f);
            else
            {
                rgb.rgb *= uQuantize; //将当前片元的颜色值乘以量化值
                rgb.rgb += new vec3(0.5f, 0.5f, 0.5f);                 //卡通化程度
                ivec3 intrgb = new ivec3(rgb.rgb);                  //转换成整数类型的向量
                rgb.rgb = new vec3(intrgb) / uQuantize;             //将整数类型的片元颜色值除以量化值
                outColor = new vec4(rgb, 1.0f);					//获得重新计算的最终颜色值
            }
        }
    }
}
